Skip to content

了解 ASP.NET Core 基础知识

ASP.NET Core 项目模板

.NET SDK 包括用于创建 ASP.NET Core 项目和文件的内置模板。 ASP.NET Core 项目模板用于使用必要的文件、文件夹和配置来创建新的 ASP.NET Core 项目,以便高效地搭建并运行项目。

安装 .NET SDK 后,可以在终端或命令提示符中运行 .NET CLI (命令行接口)命令。 若要列出内置模板,请运行 dotnet new list 命令:

sh
$ dotnet new list
这些模板已匹配你的输入:

模板名                                   短名称                      语言        标记
---------------------------------------  --------------------------  ----------  --------------------------
API 控制器                               apicontroller               [C#]        Web/ASP.NET
ASP.NET Core gRPC 服务                   grpc                        [C#]        Web/gRPC/API/Service
ASP.NET Core Web API                     webapi                      [C#],F#     Web/Web API/API/Service
ASP.NET Core Web API (native AOT)        webapiaot                   [C#]        Web/Web API/API/Service
ASP.NET Core Web 应用                    webapp,razor                [C#]        Web/MVC/Razor Pages
ASP.NET Core Web 应用(模型-视图-控制器)  mvc                         [C#],F#     Web/MVC
ASP.NET Core                          web                         [C#],F#     Web/Empty
Blazor Web 应用                          blazor                      [C#]        Web/Blazor/WebAssembly
Blazor WebAssembly 应用                  blazorwasm                  [C#]        Web/Blazor/WebAssembly/PWA
dotnet gitignore 文件                    gitignore,.gitignore                    Config
Dotnet 本地工具清单文件                  tool-manifest                           Config
EditorConfig 文件                        editorconfig,.editorconfig              Config
global.json file                         globaljson,global.json                  Config
MSBuild Directory.Build.props 文件       buildprops                              MSBuild/props
MSBuild Directory.Build.targets 文件     buildtargets                            MSBuild/props
MSTest Playwright Test Project           mstest-playwright           [C#]        Test/MSTest/Playwright
MSTest Test Project                      mstest                      [C#],F#,VB  Test/MSTest
MVC ViewImports                          viewimports                 [C#]        Web/ASP.NET
MVC ViewStart                            viewstart                   [C#]        Web/ASP.NET
MVC 控制器                               mvccontroller               [C#]        Web/ASP.NET
NuGet 配置                               nugetconfig,nuget.config                Config
NUnit 3 Test Item                        nunit-test                  [C#],F#,VB  Test/NUnit
NUnit 3 Test Project                     nunit                       [C#],F#,VB  Test/NUnit
NUnit Playwright Test Project            nunit-playwright            [C#]        Test/NUnit/Playwright
Razor 类库                               razorclasslib               [C#]        Web/Razor/Library
Razor 组件                               razorcomponent              [C#]        Web/ASP.NET
Razor 视图                               view                        [C#]        Web/ASP.NET
Razor 页面                               page                        [C#]        Web/ASP.NET
Web 配置                                 webconfig                               Config
Windows 窗体应用                         winforms                    [C#],VB     Common/WinForms
Windows 窗体控件库                       winformscontrollib          [C#],VB     Common/WinForms
Windows 窗体类库                         winformslib                 [C#],VB     Common/WinForms
WPF 应用程序                             wpf                         [C#],VB     Common/WPF
WPF 用户控件库                           wpfusercontrollib           [C#],VB     Common/WPF
WPF 类库                                 wpflib                      [C#],VB     Common/WPF
WPF 自定义控件库                         wpfcustomcontrollib         [C#],VB     Common/WPF
xUnit Test Project                       xunit                       [C#],F#,VB  Test/xUnit
协议缓冲区文件                           proto                                   Web/gRPC
控制台应用                               console                     [C#],F#,VB  Common/Console
类库                                     classlib                    [C#],F#,VB  Common/Library
解决方案文件                             sln,solution                            Solution
辅助角色服务                             worker                      [C#],F#     Common/Worker/Web

项目模板自定义选项

所有 .NET 项目模板都提供自定义选项,以便根据特定需求定制生成的项目,并使用其他服务对其进行扩展。 例如,可以为数据库访问、身份验证、OpenAPI、缓存、日志记录等添加 Entity Framework Core,使应用程序能够有效地满足特定要求。

若要查看特定模板的所有自定义选项,请使用以下 dotnet new 命令及 --help 选项,并将 <template-name> 替换为你要探索的模板的名称:

sh
$ dotnet new <template-name> --help

使用 .NET CLI dotnet new 命令创建项目

可以使用 dotnet new <template-name> 命令创建新项目。 例如,若要创建新的空白 ASP.NET Core Web 应用项目,可以运行 dotnet new web

创建新的 .NET 项目后,可以使用 dotnet builddotnet run 命令生成并运行项目。

构建你的第一个 ASP.NET Core Web 应用

使用模板创建 ASP.NET Core Web 应用项目

sh
$ dotnet new web -o MyWebApp
已成功创建模板“ASP.NET Core 空”。

正在处理创建后操作...
正在还原 D:\dotnet\MyWebApp\MyWebApp.csproj:
  正在确定要还原的项目…
  已还原 D:\dotnet\MyWebApp\MyWebApp.csproj (用时 83 毫秒)。
已成功还原。

检查项目结构

以下部分概述了空 ASP.NET Core 项目的主要项目文件夹和文件:

MyWebApp.csproj 项目文件

.csproj 项目文件用于:

配置生成项目的方式 指定面向哪个 .NET 版本 管理项目依赖项

obj 文件夹

obj 文件夹包含生成系统使用的中间文件,其中包括从源文件生成的已编译对象文件。 最终生成输出放置在生成过程中创建的 bin 文件夹中。

Properties/launchSettings.json 文件

Properties/launchSettings.json 文件包含有关如何在开发过程中启动应用的配置数据。 这些设置包括 applicationUrl 属性,该属性指定应用使用的根 URL,例如 https://localhost:{port},其中 {port} 是创建项目时分配的随机本地端口号。

launchSettings.json 文件包含以下配置:

json
{
  "$schema": "https://json.schemastore.org/launchsettings.json",
  "profiles": {
    "http": {
      "commandName": "Project",
      "dotnetRunMessages": true,
      "launchBrowser": true,
      "applicationUrl": "http://localhost:5024",
      "environmentVariables": {
        "ASPNETCORE_ENVIRONMENT": "Development"
      }
    },
    "https": {
      "commandName": "Project",
      "dotnetRunMessages": true,
      "launchBrowser": true,
      "applicationUrl": "https://localhost:7042;http://localhost:5024",
      "environmentVariables": {
        "ASPNETCORE_ENVIRONMENT": "Development"
      }
    }
  }
}

Program.cs 文件

Program.cs 文件用作 ASP.NET Core 应用的入口点,并具有多个关键用途,其中包括:

主机配置:配置主机,包括设置 Web 服务器。 服务注册:将服务添加到应用的功能,例如数据库上下文、记录和特定框架的专用服务。 中间件管道配置:将应用的请求处理管道定义为一系列中间件实例。 环境配置:为开发、过渡和生产环境设置特定于环境的设置。 在创建的新的空 ASP.NET Core 项目中,Program.cs 文件至少包含以下代码:

c#
var builder = WebApplication.CreateBuilder(args);
var app = builder.Build();

app.MapGet("/", () => "Hello World!");

app.Run();

此文件中的以下代码行创建具有预配置默认值的 WebApplicationBuilder,并生成应用:

c#
var builder = WebApplication.CreateBuilder(args);
var app = builder.Build();

app.MapGet() 方法直接定义处理 HTTP GET 请求的终结点:

c#
app.MapGet("/", () => "Hello World!");

app.MapGet("/"):定义 HTTP GET 请求的路由。 / 指示此路由响应对应用根 URL 发出的请求。 例如 http://localhost:{port}/,其中 {port} 是项目创建时在 Properties/launchSettings.json 文件中分配的随机分配端口号。

() => "Hello World!":用作请求处理器的 Lambda 表达式。 向根 URL 发出 GET 请求时,将执行此 Lambda 表达式,并返回字符串“Hello World!”

在本地运行 Web 应用

sh
$ dotnet run
正在生成...
info: Microsoft.Hosting.Lifetime[14]
      Now listening on: http://localhost:5024
info: Microsoft.Hosting.Lifetime[0]
      Application started. Press Ctrl+C to shut down.
info: Microsoft.Hosting.Lifetime[0]
      Hosting environment: Development
info: Microsoft.Hosting.Lifetime[0]
      Content root path: D:\dotnet\MyWebApp

Web 应用获得服务的方式

生成并运行应用时,将执行以下步骤:

  1. 生成和配置:

调用 MSBuild 以还原依赖项并编译项目。 MSBuild 处理 MyWebApp.csproj 项目文件并将源代码编译为程序集。 应用将读取配置设置,包括为默认启动配置文件(列出的第一个)在 launchSettings.json 中指定的配置设置。

  1. 主机设置:

Program.cs 中的 CreateHostBuilder 方法将设置 Web 主机。 默认情况下,WebHostBuilder 将 Kestrel 配置为 Web 服务器。 Kestrel 是适用于 ASP.NET Core 的跨平台 Web 服务器,专为高性能而设计。 Kestrel 开始侦听已配置 URL 上的传入 HTTP 请求,包括 HTTPS(如果指定)。

  1. 请求处理:

收到请求后,Kestrel 将其转发到 ASP.NET Core 中间件管道。 中间件管道通过一系列中间件组件处理请求,这些组件可以处理身份验证、事件日志和路由等任务。 如果请求与定义的路由匹配,则执行相应的终结点。 在这种情况下,app.MapGet("/", () => "Hello World!") 终结点处理对根 URL 的请求,并返回字符串 Hello World!。

  1. 响应:

响应(在本例中为字符串“Hello World!”)通过中间件管道发送回 Kestrel,然后 Kestrel 将其发送回客户端。

使用 dotnet watch 运行 Web 应用

使用 .NET CLI dotnet watch 命令增强开发工作流。 与命令 dotnet run 不同,每当对源文件进行更改时,dotnet watch 都会自动重新生成并重新运行应用程序。 此外,dotnet watch 还包含热重载功能,该功能会将更新直接注入正在运行的应用程序,而无需重启。 dotnet watch 使你能够更快地查看更改的结果、提高工作效果和效率。

sh
$ dotnet watch
dotnet watch 🔥 Hot reload enabled. For a list of supported edits, see https://aka.ms/dotnet/hot-reload.
  💡 Press "Ctrl + R" to restart.
dotnet watch 🔧 Building...
  正在确定要还原的项目…
  所有项目均是最新的,无法还原。
  MyWebApp -> D:\dotnet\MyWebApp\bin\Debug\net8.0\MyWebApp.dll
dotnet watch 🚀 Started
info: Microsoft.Hosting.Lifetime[14]
      Now listening on: http://localhost:5024
info: Microsoft.Hosting.Lifetime[0]
      Application started. Press Ctrl+C to shut down.
info: Microsoft.Hosting.Lifetime[0]
      Hosting environment: Development
info: Microsoft.Hosting.Lifetime[0]
      Content root path: D:\dotnet\MyWebApp
更改应用的代码并快速查看结果

MyWebApp 应用程序仍在运行,浏览器仍显示 Hello World! 响应:

  1. 在 Visual Studio Code 的“资源管理器”窗格中选择“Program.cs”。
  2. 更改 app.MapGet 方法,使其响应 "Hello .NET Developer Community!" 而不是 "Hello World!"。
  3. 保存对代码所做的更改。

保存更改后,dotnet watch 将自动检测对 Program.cs 文件的修改。 然后,它将:

  • 热重载应用程序:在可能的情况下,dotnet watch 会将更改应用到正在运行的应用程序,而无需完全重新生成。
  • 重新生成应用程序(如有必要):如果无法热重载更改,dotnet watch 会自动重新生成应用程序以合并所做的更改。
  • 重启应用程序(如有必要):如果需要完全重新生成,dotnet watch 会重启应用程序。

终端中的输出指示文件 Program.cs 已更改,并且更改已热重载到正在运行的应用。

若要查看更改的结果,请刷新浏览器。 将显示更新后的响应“Hello .NET Developer Community!”。

通过此自动重新生成和重启过程,可以快速查看更改的结果,而无需手动停止和重启应用程序。

sh
$ dotnet watch
dotnet watch 🔥 Hot reload enabled. For a list of supported edits, see https://aka.ms/dotnet/hot-reload.
  💡 Press "Ctrl + R" to restart.
dotnet watch 🔧 Building...
  正在确定要还原的项目…
  所有项目均是最新的,无法还原。
  MyWebApp -> D:\dotnet\MyWebApp\bin\Debug\net8.0\MyWebApp.dll
dotnet watch 🚀 Started
info: Microsoft.Hosting.Lifetime[14]
      Now listening on: http://localhost:5024
info: Microsoft.Hosting.Lifetime[0]
      Application started. Press Ctrl+C to shut down.
info: Microsoft.Hosting.Lifetime[0]
      Hosting environment: Development
info: Microsoft.Hosting.Lifetime[0]
      Content root path: D:\dotnet\MyWebApp
dotnet watch File changed: .\Program.cs.
dotnet watch 🔥 Hot reload of changes succeeded.
dotnet watch File changed: .\Program.cs.
dotnet watch No hot reload changes to apply.

使用中间件自定义 ASP.NET Core 行为

终端和非终端中间件

每个中间件都可以视为终端或非终端中间件。 非终端中间件会处理请求,然后调用管道中的下一个中间件。 终端中间件是管道中的最后一个中间件,没有下一个要调用的中间件。

使用 app.Use() 添加的委托可以是终端或非终端中间件。 这些委托需要一个 HttpContext 对象和一个 RequestDelegate 对象作为参数。 通常情况下,委托包括 await next.Invoke();。 这会将控制权传递给管道上的下一个中间件。 该行之前的代码在下一个中间件之前运行,该行之后的代码在下一个中间件之后运行。 使用 app.Use() 添加的委托在响应发送到客户端之前有两次机会对请求采取行动;一次是在终端中间件生成响应之前,另一次是在终端中间件生成响应之后。

使用 app.Run() 添加的委托始终是终端中间件。 不会调用管道中的下一个中间件。 是运行的最后一个中间件组件。 只需要 HttpContext 对象作为参数。 app.Run() 是添加终端中间件的快捷方式。

c#
app.Use(async (context, next) =>
{
    await context.Response.WriteAsync("Hello from middleware 1. Passing to the next middleware!\r\n");

    // Call the next middleware in the pipeline
    await next.Invoke();

    await context.Response.WriteAsync("Hello from middleware 1 again!\r\n");
});

app.Run(async context =>
{
    await context.Response.WriteAsync("Hello from middleware 2!\r\n");
});

使用内置中间件

c#
app.MapGet("/about", () => "helloworld.study");
app.UseRewriter(new RewriteOptions().AddRedirect("history", "about"));

此代码添加 URL 重写程序中间件组件,该组件用于将请求从 /history 重定向到 /about。 AddRedirect() 方法采用两个参数:用于匹配请求路径的正则表达式模式,以及要重定向到的替换路径。

创建自定义中间件

对于每个请求,它应记录请求方法、路径和响应状态代码。 紧接在 app.Run() 之前,插入以下代码:

c#
app.Use(async (context, next) =>
{
    Console.WriteLine($"{context.Request.Method} {context.Request.Path} {context.Response.StatusCode}");
    await next();
});

在上述代码中:

app.Use() 向管道添加一个自定义中间件组件。 该组件采用一个 HttpContext 对象和一个 RequestDelegate 对象作为参数。 delegate 将请求方法、路径和响应状态代码写入到控制台。 await next() 调用管道中的下一个中间件组件。

更改中间件的顺序

应用似乎正常工作,但存在问题。 你请求了 /history 页,但控制台输出没有显示它。 之所以发生此行为,是因为用于记录请求详细信息的自定义中间件组件是在 URL 重写器中间件之后添加的。 URL 重写器中间件将请求从 /history 重定向到 /about 并发送响应,自定义中间件组件看不到请求。 让我们来解决此问题。

将你添加的 app.Use() 行移动到 app.UseRewriter() 行的正前方。

c#
app.Use(async (context, next) =>
{
    Console.WriteLine($"{context.Request.Method} {context.Request.Path} {context.Response.StatusCode}");
    await next();
});

app.MapGet("/", () => "Hello .NET Developer Community!");
app.UseRewriter(new RewriteOptions().AddRedirect("hello", "/"));

app.MapGet("/about", () => "helloworld.study");
app.UseRewriter(new RewriteOptions().AddRedirect("history", "about"));

修复状态代码

该应用几乎已准备就绪,但还有一个问题。 控制台输出中的状态代码始终为 200,即使应用重定向了请求也是如此。 /history 请求的状态代码应为 302 重定向。 发生此行为是因为处理中间件组件的顺序存在另一个问题。

自定义中间件组件将详细信息记录到控制台,然后调用 await next() 来传递给下一个中间件组件。 问题是,StatusCode 对象的 Response 属性是在终端中间件组件启动响应后设置的。 让我们更改代码以修复此问题。

在你添加的委托中,将 Console.WriteLine() 行移动到 await next() 行之后。

c#
app.Use(async (context, next) =>
{
    await next();
    Console.WriteLine($"{context.Request.Method} {context.Request.Path} {context.Response.StatusCode}");
});

Last updated:

Released under the MIT License.